package com.unitd.modules.configcenter.api;

import com.unitd.frame.springweb.controller.result.AjaxResult;
import com.unitd.modules.comm.exception.ConfigServerException;
import com.unitd.modules.comm.web.BaseController;
import com.unitd.modules.configcenter.component.ConfigStateHolder;
import com.unitd.modules.configcenter.component.CryptComponent;
import com.unitd.modules.configcenter.entity.AppConfigs;
import com.unitd.modules.configcenter.entity.AppSecret;
import com.unitd.modules.configcenter.entity.Apps;
import com.unitd.modules.configcenter.service.IAppConfigsService;
import com.unitd.modules.configcenter.service.IAppsService;
import com.unitd.modules.configcenter.service.IOperateLogsService;
import com.unitd.modules.configcenter.util.ConfigParseUtils;
import com.unitd.modules.sso.util.SecurityUtil;
import com.unitd.frame.comm.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Hudan
 * @version 1.0
 * @desc api接口类, 用于对配置中心客服端提供响应接口
 * @filename AppController.java
 * @copyright www.unitd.com
 * @date 2018/1/31
 */
@RestController
@RequestMapping("/api")
public class ConfigCenterApiController extends BaseController {

	@Autowired
	private IAppConfigsService appConfigsService;
	@Autowired
	private IAppsService appsService;
	@Autowired
	private IOperateLogsService operateLogsService;
	@Autowired
	private CryptComponent cryptComponent;
	@Autowired
	private ConfigStateHolder configStateHolder;

	/**
	 * @desc 配置中心客户端服务启动的时候,调用此接口,从配置中心服务端中获取相应的属性配置信息
	 * @param appName 应用名称
	 * @param env 应用所属环境
	 * @param version 应用相应版本
	 * @return 按照键值对存储的属性配置信息
	 */
	@RequestMapping(value = "fetch_all_configs", method = RequestMethod.GET)
	public Map<String, Object> downConfigFile(@RequestParam(value = "appName") String appName,
									   @RequestParam(value = "env") String env,
									   @RequestParam(value = "version", required = false) String version) {

		if (StringUtils.isBlank(version) || "0.0.0".equals(version)) version = "releasse";

		Apps appEntity = appsService.findByName(appName);
		if (appEntity == null) throw new ConfigServerException(1001, "app不存在");

		AppConfigs globalConfig = appConfigsService.findGlobalConfig(env, version);
		//再查应用的
		Map<String, Object> queyParams = new HashMap<>(3);
		queyParams.put("env", env);
		queyParams.put("version", version);
		queyParams.put("appId", appEntity.getId());
		List<AppConfigs> appConfigs = appConfigsService.findByQueryParams(queyParams);

		if (globalConfig == null && appConfigs.isEmpty()) {
			throw new ConfigServerException(1001, "配置不存在");
		}

		Map<String, Object> result = new HashMap<>();
		if (globalConfig != null) {
			ConfigParseUtils.parseConfigToKVMap(result, globalConfig);
		}

		for (AppConfigs config : appConfigs) {
			ConfigParseUtils.parseConfigToKVMap(result, config);
		}

		AppSecret secretEntity = cryptComponent.getAppSecret(appEntity.getId(), env, "DES");
		if (secretEntity != null) {
			result.put("unitd.configcenter.encrypt-secret", secretEntity.getSecretKey());
		}

		operateLogsService.insertSelective(SecurityUtil.getOperateLog().addBizData("env", env).addBizData("appName", appName));
		return result;
	}

	/**
	 * @desc 配置中心客户端服务从配置中心服务端获取配置信息完成后,告知服务端信息获取完成,更改相应的状态信息
	 * @param params 请求参数
	 * @return 自定义的通用json对象
	 */
	@RequestMapping(value = "notify_final_config", method = RequestMethod.POST)
	public AjaxResult notifyFinalConfig(@RequestBody Map<String, String> params) {
		configStateHolder.add(new ConfigStateHolder.ConfigState(params));
		return new AjaxResult("通知成功!");
	}

	/**
	 * @desc 配置中心客户端轮询向服务端发起心跳查询
	 * @param params 请求参数
	 * @return 自定义的通用json对象
	 */
	@RequestMapping(value = "sync_status", method = RequestMethod.POST)
	public AjaxResult syncStatus(@RequestBody Map<String, String> params) {
		String env = params.remove("env");
		String appName = params.remove("appName");
		String nodeId = params.remove("nodeId");

		ConfigStateHolder.ConfigState configState = null;
		List<ConfigStateHolder.ConfigState> states = configStateHolder.get(appName, env);
		for (ConfigStateHolder.ConfigState cs : states) {
			if (cs.getNodeId().equals(nodeId)) {
				configState = cs;
				break;
			}
		}

		Map<String, String> result = new HashMap<>(1);
		if (configState != null) {
			configState.update(nodeId, params);
			result.putAll(configState.getWaitingSyncConfigs());
			// 应该在配置通知节点返回成功后执行
			configState.onConfigSyncSuccess();
		}
		return new AjaxResult(result);
	}

	@RequestMapping(value = "ping", method = RequestMethod.GET)
	public String ping() {
		return "200";
	}
}